.syntax unified                 		  /*统一指令集语法*/
.cpu cortex-m3                  		  /*指定目标处理器*/
.thumb                          		  /*类似于.code 16,选择使用thumb指令集*/

/*定义寄存器的地址*/
.equ RCC_CR, 0x40021000
.equ RCC_CFGR, 0x40021004
.equ RCC_CIR, 0x40021008
.equ FLASH_ACR, 0x40022000 
.equ INIT_TIMEOUT, 0x00000500             /*超时值*/
.equ SCB_VTOR, 0xE000ED08

.global SystemInit						  /*全局标号*/
.text									  /*代码段*/
.type SystemInit, %function               /*定义系统初始化函数*/
SystemInit:
	mov r7, lr                            /*保存返回地址*/

/*将CR寄存器的位0置1,开启内部8MHz振荡器*/
	ldr r0, =RCC_CR                       /*这里的ldr是伪指令，r0存放RCC_CR寄存器的地址*/
	ldr r1, =0x00000001                   /*这里的ldr是伪指令，r1存放用于设置RCC_CR寄存器的值*/
	ldr r2, [r0,#0]                       /*用法LDR Rd, [Rn, #offset],加载RCC_CR寄存器的内容到r1*/
	orr r2, r1                            /*按位或操作，将r2中的位0置1*/
	str r2, [r0,#0]                       /*用法STR Rd, [Rn, #offset]，将r2中的值写入RCC_CR寄存器*/
	
/*清0 RCC_CFGR寄存器的SW,HPRE,PPRE1,PPRE2,ADCPRE和MCO位*/
	ldr r0, =RCC_CFGR                     
	ldr r1, =0xf8ff0000                   
	ldr r2, [r0,#0]
	and r2, r1                            /*按位与和 C 的”&”功能相同*/
	str r2, [r0,#0]
	
/*清0 RCC_CR寄存器的HSEON, CSSON和PLLON位*/
	ldr r0, =RCC_CR
	ldr r1, =0xfef6ffff
	ldr r2, [r0,#0]
	and r2, r1
	str r2, [r0,#0]
	
/*清0 RCC_CR寄存器的HSEBYP位*/
	ldr r0, =RCC_CR
	ldr r1, =0xfffbffff
	ldr r2, [r0,#0]
	and r2, r1
	str r2, [r0,#0]
	
/*清0 RCC_CFGR寄存器的PLLSRC, PLLXTPRE, PLLMUL和USBPRE/OTGFSPRE位*/
	ldr r0, =RCC_CFGR
	ldr r1, =0xff80ffff
	ldr r2, [r0,#0]
	and r2, r1
	str r2, [r0,#0]
	
/*禁止所有的中断和清除挂起标志位*/
	ldr r0, =RCC_CIR
	ldr r1, =0x009f0000
	str r1, [r0,#0]
	
	bl SetSysClock                          /*带返回值的跳转，跳转到SetSysClock函数*/
/*向量表定位到Flash*/
	ldr r0, =SCB_VTOR
	ldr r1, =0x08000000
	str r1, [r0,#0]
	
	bx r7                                   /*返回*/  
	
/*SetSysClock函数用于设置系统时钟频率，HCLK,PCLK2和PCLK1的预分频器*/
.type SetSysClock, %function
SetSysClock:
/*外部高速时钟使能*/
	ldr r0, =RCC_CR
	ldr r1, =0x00010000
	ldr r2, [r0,#0]
	orr r2, r1
	str r2, [r0,#0]
	
/*检测RCC_CR寄存器的位17(HSERDY)，外部高速时钟就绪标志*/
/*判断是否初始化超时*/
	ldr r3, =INIT_TIMEOUT                  /*设置超时值*/
test_HSERDY_bit:
	ldr r1, =0x00020000
	ldr r2, [r0,#0]                        /*读取寄存器RCC_CR的数据*/
	and r2, r1                             /*读取HSERDY位的值*/
	cmp r2, #0                             /*比较指令，用于判断外部高速时钟就绪标志*/
	beq test_timeout
	b   set_clock                          /*如果外部高速时钟就绪，去设置时钟*/
test_timeout:
	sub r3, #1
	cmp r3, #0                             /*判断是否超时*/
timeout:
	beq timeout                            /*如果超时，死循环*/
	b   test_HSERDY_bit                    /*如果没超时，就继续检测HSERDY位*/

/*如果就绪完毕，设置时钟*/
set_clock:
/*FLASH_ACR寄存器的位4,预取缓冲区使能*/
	ldr r0, =FLASH_ACR
	ldr r1, =0x00000010
	ldr r2, [r0,#0]
	orr r2, r1
	str r2, [r0,#0]
/*FLASH_ACR寄存器的位2~0,设置时延*/
	ldr r1, =0xfffffff8
	ldr r2, [r0,#0]
	and r2, r1                             /*清0FLASH_ACR寄存器的位2~0*/
	ldr r1, =0x00000002
	orr r2, r1                             /*设置时延为两个等待状态*/
	str r2, [r0,#0]
/*设置时钟配置寄存器(RCC_CFGR)，设置预分频器*/
	ldr r0, =RCC_CFGR
	ldr r1, =0x00000000
	ldr r2, [r0,#0]
	orr r2, r1          
	str r2, [r0,#0]                       /*设置AHB预分频器不分频，HCLK=72MHz*/
	
	ldr r1, =0x00000000
	ldr r2, [r0,#0]
	orr r2,r1
	str r2, [r0,#0]                       /*设置APB2预分频器不分频，PCLK2=72MHz*/
	
	ldr r1, =0x00000400
	ldr r2, [r0,#0]
	orr r2, r1 
	str r2, [r0,#0]                       /*设置APB1预分频器2分频，PCLK1=36MHz*/
/*设置时钟配置寄存器(RCC_CFGR)，配置PLL*/
	ldr r1, =0xffc0ffff
	ldr r2, [r0,#0]
	and r2, r1 
	ldr r1, =0x001d0000
	orr r2, r1 
	str r2, [r0,#0]                       /*HSE不分频,HSE时钟作为PLL输入时钟,PLL 9倍频输出*/
/*使能PLL*/
	ldr r0, =RCC_CR
	ldr r1, =0x01000000
	ldr r2, [r0,#0]
	orr r2, r1 
	str r2, [r0,#0]
/*等待PLL就绪*/
test_PLLRDY_bit:
	ldr r1, =0x02000000
	ldr r2, [r0,#0]
	and r2, r1 
	cmp r2, #0
	beq test_HSERDY_bit
/*设置时钟配置寄存器(RCC_CFGR)，PLL输出作为系统时钟*/
	ldr r0, =RCC_CFGR
	ldr r1, =0xfffffffc
	ldr r2, [r0,#0]
	and r2, r1 
	ldr r1, =0x00000002
	orr r2, r1 
	str r2, [r0,#0]
/*等待系统时钟切换就绪*/
test_SWS_bit:
	ldr r1, =0x0000000c
	ldr r2, [r0,#0]
	and r2, r1 
	cmp r2, #8
	bne test_SWS_bit
	
	bx lr                                /*返回*/
	
	.end                                 /*文件结束*/
	